package transaction;

import java.io.*;

import utils.Constants;
import utils.Converter;

public class Logger {
	
	private DataOutputStream writer;
	
	BufferedOutputStream bstream;
	
	public final boolean NeedHeader;
	
	public Logger() {
		if (TxManager.WriteLog) {
			File f = new File(Constants.LOG_FILENAME);
			NeedHeader = !f.exists();
			
			try {	
				FileOutputStream fstream = new FileOutputStream(Constants.LOG_FILENAME, true);
				bstream = new BufferedOutputStream(fstream, 4096);
				writer = new DataOutputStream(bstream);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else
			NeedHeader = false;
	}

	
	public void logInt(int value) {
		if (TxManager.WriteLog)
			try {
				writer.writeInt(value);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	public void logString(String value) {
		if (TxManager.WriteLog)
			try {
				byte[] bytes = new byte[value.length()];
				Converter.String2Bytes(value, bytes, 0);
				writer.writeInt(bytes.length);
				writer.write(bytes, 0, bytes.length);
				
				bstream.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logBegin(int txNum) {
		if (TxManager.WriteLog)
			try {
				writer.writeInt(TxManager.TxBegin);
				writer.writeInt(txNum);
				
				bstream.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logCommit(int txNum) {
		if (TxManager.WriteLog)
			try {
				writer.writeInt(TxManager.TxCommit);
				writer.writeInt(txNum);
				
				bstream.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logAppendInt(int txNum, int fileId, int pageId, int offset, int value) {
		if (TxManager.WriteLog)
			try {
				writer.writeInt(TxManager.AppendInt);
				writer.writeInt(txNum);
				writer.writeInt(fileId);
				writer.writeInt(pageId);
				writer.writeInt(offset);
				writer.writeInt(value);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logAppendLong(int txNum, int fileId, int pageId, int offset, long value) {
		if (TxManager.WriteLog)
			try {
				writer.writeInt(TxManager.AppendInt);
				writer.writeInt(txNum);
				writer.writeInt(fileId);
				writer.writeInt(pageId);
				writer.writeInt(offset);
				writer.writeLong(value);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logAppendBytes(int txNum, int fileId, int pageId, int offset, 
			byte[] bytes, int start, int length) {
		if (TxManager.WriteLog)
			try {
				//System.out.println(" >>> logAppendBytes " + txNum);
				
				writer.writeInt(TxManager.AppendBytes);
				writer.writeInt(txNum);
				writer.writeInt(fileId);
				writer.writeInt(pageId);
				writer.writeInt(offset);
				writer.writeInt(length);
				writer.write(bytes, start, length);
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logWriteInt(int txNum, int fileId, int pageId, 
			int offset, int oldValue, int newValue) {
		if (TxManager.WriteLog)
			try {
				//System.out.println(" >>> logWriteInt " + txNum);
				
				writer.writeInt(TxManager.WriteInt);
				writer.writeInt(txNum);
				writer.writeInt(fileId);
				writer.writeInt(pageId);
				writer.writeInt(offset);
				writer.writeInt(oldValue);
				writer.writeInt(newValue);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	synchronized public void logWriteLong(int txNum, int fileId, int pageId, 
			int offset, long oldValue, long newValue) {
		if (TxManager.WriteLog)
			try {
				//System.out.println(" >>> logWriteLong " + txNum);
				
				writer.writeInt(TxManager.WriteLong);
				writer.writeInt(txNum);
				writer.writeInt(fileId);
				writer.writeInt(pageId);
				writer.writeInt(offset);
				writer.writeLong(oldValue);
				writer.writeLong(newValue);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	
	/*
	public void logWriteBytes(int txNum, int fileId, int pageId, int offset, 
			byte[] oValue, int oStart, int oLength,
			byte[] nValue, int nStart, int nLength) {
		
	}
	*/
	
	public void dispose() {		
		if (TxManager.WriteLog)
			try {
				writer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
}
